
`include "adder_32bit.v"
`include "signextend.v"

// TODO: make sure this will allow you to jump BACKWARDS!


// Calculates the address of the next instruction
module FetchUnit(nPC_sel, jump_sel, imm16, imm26, Instruction, CLK);
input nPC_sel, CLK, jump_sel;
input [15:0] imm16;
input [25:0] imm26;
//input [31:0] currentPC;
output [31:0] Instruction;

wire [31:0] add1, add2, immed16ext, 
            immed26ext, toJumpMux, toPC, 
			instrAddr;

// Extend the immediate16
SIGN_EXTEND PC_ext (imm16,immed16ext);

// Extend the immediate 26
SIGN_EXTEND_26bitto32bit PC_ext26(imm26, imm26ext);

adder_32bit add4toPC (add1,4,instrAddr);
adder_32bit addImm16toPC(add2,immed16ext,add1);
adder_32bit addImm26toPC(add3,immed26ext,instrAddr);

// Apply the control signals to choose between the possibilities
MUX32_2to1 nextOrBranch (add1,add2,nPC_sel,toJumpMux);
MUX32_2to1 nextOrJump (toJumpMux, add3, jump_sel, toPC);

// Register holding the current pc
programCounter pc(toPC, instrAddr, CLK);

// Using the calculated address, get the desired instruction
InstrMem instructionMemory (instrAddr, Instruction);

endmodule
